package top.mcwebsite.playandroid.home.vm

import android.util.Log
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingSource
import androidx.paging.PagingState
import androidx.paging.cachedIn
import kotlinx.coroutines.launch
import top.mcwebsite.playandroid.business.articles.api.model.ArticleModel
import top.mcwebsite.playandroid.common.network.api.NetworkService
import top.mcwebsite.playandroid.common.network.api.createApi
import top.mcwebsite.playandroid.common.network.model.ApiResult
import top.mcwebsite.playandroid.common.uiWidget.ErrorModel
import top.mcwebsite.playandroid.home.api.HomeNetworkApi
import top.mcwebsite.playandroid.lib.mvi.base.BaseViewModel
import top.mcwebsite.playandroid.lib.mvi.model.Async
import top.mcwebsite.playandroid.lib.servicemanager.core.ServiceManager

class HomeViewModel : BaseViewModel<HomePageIntent, HomeUiState, HomePageUiEffect>(HomeUiState()) {


    private val homeNetworkApi: HomeNetworkApi =
        ServiceManager.getService<NetworkService>().createApi()

    init {
        fetchBanners()
        fetchTopArticles()
    }

    private val pager = Pager(PagingConfig(pageSize = 10)) {
        ArticlePagingSource()
    }

    val pagerFlow = pager.flow.cachedIn(viewModelScope)

    private suspend fun suspendFetchTopArticles() {
        when (val result = homeNetworkApi.getTopArticles()) {
            is ApiResult.Success -> {
                if (result.data.errorCode == 0) {
                    setUiState { copy(topArticleModels = result.data.data ?: emptyList()) }
                }
            }
            is ApiResult.Failure -> {
                setUiState {
                    copy(errorModel = ErrorModel(result.cause) {
                        setUiState { copy(errorModel = null) }
                        fetchTopArticles()
                    })
                }
            }
        }
    }

    private fun fetchTopArticles() {
        viewModelScope.launch {
            suspendFetchTopArticles()
        }
    }

    private suspend fun suspendFetchBanner() {
        if (uiState.asyncBanners is Async.UnInitialization) {
            setUiState { copy(asyncBanners = Async.Loading) }
        }
        when (val result = homeNetworkApi.getBanners()) {
            is ApiResult.Success -> {
                val banners = result.data
                if (banners.data == null) {
                    // 错误处理
                    return
                }
                if (banners.data.isNullOrEmpty()) {
                    val msg = if (banners.errorCode != 0) {
                        banners.errorMsg
                    } else {
                        banners.errorMsg
                    }
                    setUiState { copy(asyncBanners = Async.Failed(msg)) }
                } else {
                    Log.d("mengchen", "banners data = ${banners.data}")
                    setUiState { copy(asyncBanners = Async.Success(banners.data!!)) }
                }
            }
            is ApiResult.Failure -> {
                setUiState { copy(errorModel = ErrorModel(result.cause) {
                    setUiState { copy(errorModel = null) }
                    fetchBanners()
                }) }
            }
        }

    }

    private fun fetchBanners() {
        viewModelScope.launch {
            suspendFetchBanner()
        }
    }

    fun refresh() {
        viewModelScope.launch {
            setUiState { copy(isRefreshing = true) }
            suspendFetchBanner()
            fetchTopArticles()
            setUiState { copy(isRefreshing = false) }
        }
    }

    override fun handleIntent(intent: HomePageIntent) {
        when (intent) {
            is HomePageIntent.OnClickBannerIntent -> {
                sendUiEffect(HomePageUiEffect.NavigationToArticleDetailPageUiEffect(intent.bannerModel.url))
            }
            is HomePageIntent.OnClickArticleIntent -> {
                sendUiEffect(HomePageUiEffect.NavigationToArticleDetailPageUiEffect(intent.articleModel.link))
            }
        }
    }

    private inner class ArticlePagingSource : PagingSource<Int, ArticleModel>() {
        override fun getRefreshKey(state: PagingState<Int, ArticleModel>): Int? {
            return null
        }

        override suspend fun load(params: LoadParams<Int>): LoadResult<Int, ArticleModel> {
            return try {
                val nextPageNumber = params.key ?: 0
                when (val result = homeNetworkApi.getArticles(nextPageNumber)) {
                    is ApiResult.Success -> {
                        LoadResult.Page(
                            data = result.data.data?.datas ?: emptyList(),
                            prevKey = if (nextPageNumber == 0) null else nextPageNumber - 1,
                            nextKey = if (result.data.data?.over == true) null else nextPageNumber + 1
                        )
                    }
                    is ApiResult.Failure -> {
                        LoadResult.Error(result.cause)
                    }
                }
            } catch (e: Exception) {
                return LoadResult.Error(e)
            }
        }

    }


}